package cn.liumouren.tool.pac.util;

import cn.liumouren.tool.pac.constant.OrderConstant;
import cn.liumouren.tool.pac.entity.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * @author Daniel Liu
 * @date 2021/3/4 01:27
 */
public class QueryUtil {
    public static <T> void processSelect(QueryWrapper<T> queryWrapper, Query query) {
        if (!CollectionUtils.isEmpty(query.getSelect())) {
            queryWrapper.select(query.getSelect().toArray(new String[0]));
        }
    }

    public static <T> void processEq(QueryWrapper<T> queryWrapper, Query query) {
        if (query.getWhere() != null && !CollectionUtils.isEmpty(query.getWhere().getEq())) {
            Map<String, Object> eq = query.getWhere().getEq();
            String key;
            Object value;
            for (Map.Entry<String, Object> entry : eq.entrySet()) {
                key = entry.getKey();
                value = entry.getValue();
                // 可能是List
                if (value instanceof List) {
                    List<?> list = (List<?>) value;
                    for (Object o : list) {
                        queryWrapper.eq(key, o);
                    }
                } else {
                    // 单个值
                    queryWrapper.eq(key, value);
                }
            }
        }
    }

    public static <T> void processLike(QueryWrapper<T> queryWrapper, Query query) {
        if (query.getWhere() != null && !CollectionUtils.isEmpty(query.getWhere().getLike())) {
            Map<String, Object> like = query.getWhere().getLike();
            queryWrapper.and(w -> {
                String k;
                Object v;
                for (Map.Entry<String, Object> entry : like.entrySet()) {
                    k = entry.getKey();
                    v = entry.getValue();
                    // 可能是List
                    if (v instanceof List) {
                        List<?> list = (List<?>) v;
                        for (Object o : list) {
                            setLike(w, k, (String) o);
                        }
                    } else {
                        // 单个值
                        setLike(w, k, (String) v);
                    }
                }
            });
        }
    }

    private static <T> void setLike(QueryWrapper<T> queryWrapper, String column, String likeStr) {
        boolean isStart = likeStr.startsWith("%");
        boolean isEnd = likeStr.endsWith("%");
        if (isStart && isEnd) {
            queryWrapper.like(column, likeStr.substring(1, likeStr.length() - 1)).or();
            return;
        }
        // 以%开头不以%结尾
        if (isStart) {
            queryWrapper.likeLeft(column, likeStr.substring(1)).or();
            return;
        }
        // 以%结尾不以%开头
        if (isEnd) {
            queryWrapper.likeRight(column, likeStr.substring(0, likeStr.length() - 1)).or();
        }
    }

    public static <T> void processOrder(QueryWrapper<T> queryWrapper, Query query) {
        if (!CollectionUtils.isEmpty(query.getOrder())) {
            Map<String, String> order = query.getOrder();
            String key;
            Object value;
            for (Map.Entry<String, String> entry : order.entrySet()) {
                key = entry.getKey();
                value = entry.getValue();
                if (OrderConstant.ASC.equalsIgnoreCase(value.toString())) {
                    queryWrapper.orderByAsc(key);
                    continue;
                }
                if (OrderConstant.DES.equalsIgnoreCase(value.toString())) {
                    queryWrapper.orderByDesc(key);
                }
            }
        }
    }

    public static <T> void processCompare(QueryWrapper<T> queryWrapper, Query query) {
        processGt(queryWrapper, query);
        processGe(queryWrapper, query);
        processLt(queryWrapper, query);
        processLe(queryWrapper, query);
    }

    private static <T> void processLe(QueryWrapper<T> queryWrapper, Query query) {
        if (query.getWhere() != null && !CollectionUtils.isEmpty(query.getWhere().getLe())) {
            Map<String, Number> le = query.getWhere().getLe();
            for (Map.Entry<String, Number> entry : le.entrySet()) {
                queryWrapper.le(entry.getKey(), entry.getValue());
            }
        }
    }

    private static <T> void processLt(QueryWrapper<T> queryWrapper, Query query) {
        if (query.getWhere() != null && !CollectionUtils.isEmpty(query.getWhere().getLt())) {
            Map<String, Number> lt = query.getWhere().getLt();
            for (Map.Entry<String, Number> entry : lt.entrySet()) {
                queryWrapper.lt(entry.getKey(), entry.getValue());
            }
        }
    }

    private static <T> void processGe(QueryWrapper<T> queryWrapper, Query query) {
        if (query.getWhere() != null && !CollectionUtils.isEmpty(query.getWhere().getGe())) {
            Map<String, Number> ge = query.getWhere().getGe();
            for (Map.Entry<String, Number> entry : ge.entrySet()) {
                queryWrapper.ge(entry.getKey(), entry.getValue());
            }
        }
    }

    private static <T> void processGt(QueryWrapper<T> queryWrapper, Query query) {
        if (query.getWhere() != null && !CollectionUtils.isEmpty(query.getWhere().getGt())) {
            Map<String, Number> gt = query.getWhere().getGt();
            for (Map.Entry<String, Number> entry : gt.entrySet()) {
                queryWrapper.gt(entry.getKey(), entry.getValue());
            }
        }
    }

    public static <T> void processIn(QueryWrapper<T> queryWrapper, Query query) {
        if (query.getWhere() != null && !CollectionUtils.isEmpty(query.getWhere().getIn())) {
            Map<String, List<?>> in = query.getWhere().getIn();
            for (Map.Entry<String, List<?>> entry : in.entrySet()) {
                queryWrapper.in(entry.getKey(), entry.getValue());
            }
        }
    }

    public static <T> void processWhere(QueryWrapper<T> queryWrapper, Query query) {
        // 处理 eq
        processEq(queryWrapper, query);

        // 处理 like
        processLike(queryWrapper, query);

        // 处理 比较关系
        processCompare(queryWrapper, query);

        // 处理 in
        processIn(queryWrapper, query);
    }
}
